package com.haixiaoke.saas.workOrder.service.impl;

import cn.hutool.core.bean.BeanUtil;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSONObject;
import com.haixiaoke.saas.common.config.WeChatConfig;
import com.haixiaoke.saas.common.config.sms.SmsConfig;
import com.haixiaoke.saas.common.constant.WorkOrderConstants;
import com.haixiaoke.saas.common.core.domain.AjaxResult;
import com.haixiaoke.saas.common.core.redis.RedisCache;
import com.haixiaoke.saas.common.enums.UserStatus;
import com.haixiaoke.saas.common.exception.ServiceException;
import com.haixiaoke.saas.common.utils.DateUtils;
import com.haixiaoke.saas.common.utils.sms.SmsUtils;
import com.haixiaoke.saas.common.weChat.domain.ParseParam;
import com.haixiaoke.saas.common.weChat.domain.UnifiedOrder;
import com.haixiaoke.saas.common.weChat.service.WeChatService;
import com.haixiaoke.saas.department.domain.WechatAccount;
import com.haixiaoke.saas.department.service.IWechatAccountService;
import com.haixiaoke.saas.order.domain.WechatPayRecord;
import com.haixiaoke.saas.order.service.IWechatPayRecordService;
import com.haixiaoke.saas.workOrder.domain.*;
import com.haixiaoke.saas.workOrder.domain.WorkOrderPerson;
import com.haixiaoke.saas.user.domain.BizUserBusiness;
import com.haixiaoke.saas.user.service.IBizUserBusinessService;
import com.haixiaoke.saas.user.service.IUserConsumerService;
import com.haixiaoke.saas.workOrder.mapper.WorkOrderMapper;
import com.haixiaoke.saas.workOrder.service.*;
import com.haixiaoke.saas.workOrder.state.server.IWorkOrderTypeServerRole;
import com.haixiaoke.saas.workOrder.state.server.WorkOrderTypeServerRole;
import org.apache.commons.lang3.RandomUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.haixiaoke.saas.common.core.domain.AjaxResult.error;
import static com.haixiaoke.saas.system.framework.datasource.DynamicDataSourceContextHolder.log;

/**
 * 工单Service业务层处理
 *
 * @author panda
 * @date 2024-09-02
 */
@Service
public class WorkOrderServiceImpl implements IWorkOrderService {
    @Autowired
    private WorkOrderMapper workOrderMapper;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private WeChatConfig weChatConfig;
    @Autowired
    private IWechatAccountService wechatAccountService;
    @Autowired
    private WeChatService weChatService;
    @Autowired
    private IWechatPayRecordService wechatPayRecordService;
    @Autowired
    private IWorkOrderChargeItemService workOrderChargeItemService;
    @Autowired
    private IWorkOrderRecordService workOrderRecordService;
    @Autowired
    private IWorkOrderPersonService workOrderPersonService;
    @Autowired
    private IBizUserBusinessService userBusinessService;
    @Autowired
    private IUserConsumerService userConsumerService;
    @Autowired
    private IWorkOrderEvaluateService workOrderEvaluateService;
    @Autowired
    private SmsUtils smsUtils;
    @Autowired
    private SmsConfig smsConfig;

    @Autowired
    private IWorkOrderPwdRecordService workOrderPwdRecordService;

    /**
     * 查询工单
     *
     * @param workOrderId 工单主键
     * @return 工单
     */
    @Override
    public WorkOrder selectWorkOrderByWorkOrderId(String workOrderId) {
        WorkOrder workOrder = workOrderMapper.selectWorkOrderByWorkOrderId(workOrderId);

        if (ObjectUtil.isNotNull(workOrder)) {
            WorkOrderEvaluate workOrderEvaluate = workOrderEvaluateService.selectWorkOrderEvaluateByWorkOrderId(workOrderId);
            workOrder.setWorkOrderEvaluation(workOrderEvaluate);


            if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_MAINTENANCE, workOrder.getWorkOrderType()) ||
                    StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_CLEANING, workOrder.getWorkOrderType())) {
                List<WorkOrderChargeItem> workOrderChargeItems = workOrderChargeItemService.selectWorkOrderChargeItemByWorkOrderId(workOrderId);
                workOrder.setWorkOrderChargeItemList(workOrderChargeItems);
            }
        }
        return workOrder;
    }

    @Override
    public WorkOrder appletSelectWorkOrderByWorkOrderId(String workOrderId) {
        WorkOrder workOrder = workOrderMapper.selectWorkOrderByWorkOrderId(workOrderId);

        if (ObjectUtil.isNotNull(workOrder)) {
            WorkOrderEvaluate workOrderEvaluate = workOrderEvaluateService.selectWorkOrderEvaluateByWorkOrderId(workOrderId);
            workOrder.setWorkOrderEvaluation(workOrderEvaluate);

            if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_CANCELED, workOrder.getWorkOrderState())) {
                WorkOrderRecord record = workOrderRecordService.selectWorkOrderRecordByRecordTypeAndUserDisplayType(workOrderId,
                        WorkOrderConstants.RECORD_TYPE_USER_VISIBLE, WorkOrderConstants.DISPLAY_TYPE_ORDER_CANCELLED);
                workOrder.setWorkOrderRecord(record);
            }
            if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_DISPATCH, workOrder.getWorkOrderState()) ||
                    StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, workOrder.getWorkOrderState()))) {
                WorkOrderRecord record = workOrderRecordService.selectWorkOrderRecordByRecordTypeAndUserDisplayType(workOrderId,
                        WorkOrderConstants.RECORD_TYPE_USER_VISIBLE, WorkOrderConstants.DISPLAY_TYPE_ORDER_ACCEPTED);
                workOrder.setReceivedWorkOrderRecord(record);
            }

            if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_MAINTENANCE, workOrder.getWorkOrderType()) ||
                    StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_CLEANING, workOrder.getWorkOrderType())) {
                List<WorkOrderChargeItem> workOrderChargeItems = workOrderChargeItemService.selectWorkOrderChargeItemByWorkOrderId(workOrderId);
                workOrder.setWorkOrderChargeItemList(workOrderChargeItems);
            }

            if (workOrder.getWorkOrderType().equals(WorkOrderConstants.WORK_ORDER_TYPE_INTERMEDIARY)){
                workOrder.setTemporaryPwdApplyState(workOrderPwdRecordService.selectWorkOrderPwdApplyStatusByWorkOrderId(workOrderId));
            }
        }
        return workOrder;
    }

    /**
     * 查询工单列表
     *
     * @param workOrder 工单
     * @return 工单
     */
    @Override
    public List<WorkOrder> selectWorkOrderList(WorkOrder workOrder) {
        List<WorkOrder> workOrderList = workOrderMapper.selectWorkOrderList(workOrder);
        if (CollectionUtil.isNotEmpty(workOrderList)) {
            //批量查询维修数据
            List<String> workOrders = workOrderList.stream().map(WorkOrder::getWorkOrderId).collect(Collectors.toList());
            List<WorkOrderChargeItem> workOrderChargeItemList = workOrderChargeItemService.selectWorkOrderChargeItemByWorkOrderIds(workOrders);

            //拼接维修项名称
            if (CollectionUtil.isNotEmpty(workOrderChargeItemList)) {
                Map<String, List<WorkOrderChargeItem>> collect = workOrderChargeItemList.stream().collect(Collectors.groupingBy(WorkOrderChargeItem::getWorkOrderId));
                for (WorkOrder order : workOrderList) {
                    List<WorkOrderChargeItem> workOrderChargeItems = collect.get(order.getWorkOrderId());

                    if (CollectionUtil.isNotEmpty(workOrderChargeItems)) {
                        order.setWorkOrderChargeItemList(workOrderChargeItems);
                        String itemName = workOrderChargeItems.stream().map(WorkOrderChargeItem::getItemName)
                                .filter(StrUtil::isNotBlank).collect(Collectors.joining("|"));
                        order.setItemName(itemName);
                    }
                }
            }
        }
        return workOrderList;
    }

    /**
     * 新增工单
     *
     * @param workOrder 工单
     * @param phone     创建工单人的手机号
     * @return 结果
     */
    @Override
    public AjaxResult insertWorkOrder(WorkOrder workOrder, String phone) {
        if (StrUtil.isBlank(workOrder.getWorkOrderType())) {
            return AjaxResult.error("工单类型异常");
        }

        //工单id
        String workOrderId = "KO" + System.currentTimeMillis() + RandomUtils.nextInt(10000, 100000);
        workOrder.setWorkOrderId(workOrderId);

        //驳回工单
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.insertWorkOrder(phone);

        return result > 0 ? AjaxResult.success(workOrderId) : AjaxResult.error();
    }

    public int insertWorkOrder(WorkOrder workOrder) {
        return workOrderMapper.insertWorkOrder(workOrder);
    }

    /**
     * 修改工单
     *
     * @param workOrder 工单
     * @return 结果
     */
    @Override
    public int updateWorkOrder(WorkOrder workOrder) {
        return workOrderMapper.updateWorkOrder(workOrder);
    }

    @Override
    public int editWorkOrder(WorkOrder workOrder) {
        return workOrderMapper.editWorkOrder(workOrder);
    }

    /**
     * 修改工单
     *
     * @param workOrder 工单
     * @param phone
     * @return 结果
     */
    @Override
    public int flatUpdateWorkOrder(WorkOrder workOrder, String phone) {
        //工单id
        if (StrUtil.isBlank(workOrder.getWorkOrderId())) {
            throw new ServiceException("工单ID不能为空");
        }

        WorkOrder wo = workOrderMapper.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        if (ObjectUtil.isNotEmpty(wo)) {
            workOrder.setWorkOrderType(wo.getWorkOrderType());
        } else {
            throw new ServiceException("工单不存在");
        }

        if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_DISPATCH, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, wo.getWorkOrderState()))) {
            throw new ServiceException("工单状态异常,无法修改");
        }

        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        return workOrderTypeServerRole.updateWorkOrder(phone);
    }

    /**
     * 批量删除工单
     *
     * @param workOrderIds 需要删除的工单主键
     * @return 结果
     */
    @Override
    public int deleteWorkOrderByWorkOrderIds(String[] workOrderIds) {
        return workOrderMapper.deleteWorkOrderByWorkOrderIds(workOrderIds);
    }

    /**
     * 删除工单信息
     *
     * @param workOrderId 工单主键
     * @return 结果
     */
    @Override
    public int deleteWorkOrderByWorkOrderId(String workOrderId) {
        return workOrderMapper.deleteWorkOrderByWorkOrderId(workOrderId);
    }

    /**
     * 创建付款二维码
     *
     * @param workOrderId
     * @return
     */
    @Override
    public AjaxResult createPayPicture(String workOrderId) {
        if (StringUtils.isEmpty(workOrderId)) {
            throw new ServiceException("工单ID不能为空");
        }
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderId);
        if (ObjectUtil.isEmpty(workOrder)) {
            throw new ServiceException("工单不存在");
        }

        if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_INTERMEDIARY, workOrder.getWorkOrderType())) {
            return AjaxResult.error("看房单不支持付款");
        }

        if (!WorkOrderConstants.WORK_ORDER_STATE_WAIT_PAY.equals(workOrder.getWorkOrderState())) {
            throw new ServiceException("工单状态异常,无法创建付款二维码");
        }

        String url = redisCache.getCacheObject(WorkOrderConstants.WORK_ORDER_NATIVE_PAY_REDIS_KEY + workOrderId);
        if (StrUtil.isEmpty(url)) {

            WechatAccount account = wechatAccountService.selectWechatAccountByTenantId(workOrder.getTenantId());
            if (ObjectUtil.isEmpty(account)) {
                return error("商家信息错误，请联系管理员");
            }
            UnifiedOrder unifiedOrder = getUnifiedOrder(account, workOrder);

            AjaxResult ajaxResult = weChatService.nativeOrder(unifiedOrder);
            url = StrUtil.toString(ajaxResult.get("data"));
            redisCache.setCacheObject(WorkOrderConstants.WORK_ORDER_NATIVE_PAY_REDIS_KEY + workOrderId, url, 120, TimeUnit.MINUTES);
        }
        return AjaxResult.success("success", url);
    }

    @Override
    public void weChatCallbackWorkOrderNativePay(ParseParam parseParam) {

        // 支付完成删除缓存
        redisCache.deleteObject(WorkOrderConstants.WORK_ORDER_NATIVE_PAY_REDIS_KEY + parseParam.getOutTradeNo());

        WorkOrder workOrder = selectWorkOrderByWorkOrderId(parseParam.getOutTradeNo());
        if (ObjectUtil.isEmpty(workOrder)) {
            log.error("查询不到工单,参数：{}", JSONObject.toJSONString(parseParam));
            return;
        }
        // 保存微信支付回到参数
        WechatPayRecord wechatPayRecord = new WechatPayRecord();
        BeanUtil.copyProperties(parseParam, wechatPayRecord);
        wechatPayRecordService.insertWechatPayRecord(wechatPayRecord);

        Date nowDate = DateUtils.getNowDate();
        WorkOrderRecord record = new WorkOrderRecord(workOrder.getWorkOrderId(), WorkOrderConstants.RECORD_TYPE_USER_VISIBLE, WorkOrderConstants.DISPLAY_TYPE_ORDER_COMPLETED,
                "工单已扫码缴费", null, null, nowDate);
        workOrder.setPaymentType(WorkOrderConstants.PAYMENT_TYPE_SCAN_CODE);
        workOrder.setPaymentTime(nowDate);

        // 更新工单状态
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        workOrderTypeServerRole.paymentCompletion(record);
    }

    private UnifiedOrder getUnifiedOrder(WechatAccount account, WorkOrder workOrder) {
        UnifiedOrder unifiedOrder = new UnifiedOrder();
        unifiedOrder.setAppId(weChatConfig.getAppId());
        unifiedOrder.setAccountId(account.getAccountId());
        unifiedOrder.setAccountApiKey(account.getAccountApiKey());
        unifiedOrder.setAttach(account.getTenantId());
        unifiedOrder.setOutTradeNo(workOrder.getWorkOrderId());
        BigDecimal totalFee = workOrder.getWorkOrderAmount();
        unifiedOrder.setCallBackUrl(weChatConfig.getWorkOrderNativePayCallBackUrl());
        unifiedOrder.setBody("房屋管家-工单支付");
        // TODO: 2024-6-5 金额写死
        unifiedOrder.setTotalFee(/*totalFee.multiply(BigDecimal.valueOf(100)).intValue()*/1);
        return unifiedOrder;
    }


    @Override
    public AjaxResult rejectWorkOrder(WorkOrderRecord workOrderRecord, String userName, String flatUserName) {
        if (StrUtil.isEmpty(workOrderRecord.getRecordContent())) {
            return AjaxResult.error("驳回原因不能为空");
        }

        WorkOrder workOrder = workOrderMapper.selectWorkOrderByWorkOrderId(workOrderRecord.getWorkOrderId());
        if (ObjectUtil.isNotEmpty(workOrder)) {

            //驳回工单
            IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
            int result = workOrderTypeServerRole.rejectWorkOrder(workOrderRecord, userName, flatUserName);
            return result > 0 ? AjaxResult.success() : AjaxResult.error();
        }
        return AjaxResult.error("工单不存在");
    }

    @Override
    public AjaxResult dispatchWorkOrder(WorkOrder workOrder) {

        WorkOrderPerson workOrderPerson = workOrderPersonService.selectWorkOrderPersonByBusUserId(workOrder.getBusUserId(), workOrder.getPersonTenantId());

        if (ObjectUtil.isEmpty(workOrderPerson)) {
            return AjaxResult.error("该业务员没有维修权限");
        }
        BizUserBusiness userBusiness = userBusinessService.selectBizUserBusinessByUserId(workOrderPerson.getBusUserId(), workOrderPerson.getTenantId());
        if (ObjectUtil.isEmpty(userBusiness)) {
            return AjaxResult.error("账号异常");
        }
        if (UserStatus.DISABLE.getCode().equals(userBusiness.getStatus())) {
            return AjaxResult.error("账号被停用");
        }

        WorkOrder wo = this.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        //待派单,待接单,待审核以外的工单不能派单
        if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_DISPATCH, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_AUDIT, wo.getWorkOrderState()))) {
            return AjaxResult.error("工单状态不正确，无法派单");
        }

        if (wo.getBusUserId() != null && wo.getBusUserId().equals(workOrderPerson.getBusUserId())) {
            return AjaxResult.error("不能派单给自己");
        }

        wo.setUpdateBy(workOrder.getUpdateBy());
        wo.setBusUserId(workOrder.getBusUserId());
        wo.setPersonTenantId(workOrder.getPersonTenantId());
        if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_MAINTENANCE, wo.getWorkOrderType()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_CLEANING, wo.getWorkOrderType())) {
            wo.setDisposeTimeLimit(workOrder.getDisposeTimeLimit());
            wo.setPayer(workOrder.getPayer());
        }
        //派单,改派工单
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(wo);
        int result = workOrderTypeServerRole.dispatchWorkOrder(workOrderPerson);
        if (result > 0) {
            smsUtils.sendTemplateSmsWithData(workOrderPerson.getWorkOrderPersonPhone(), smsConfig.getWorkOrderTemplateCode(),
                    new String[]{workOrderPerson.getWorkOrderPersonName(), wo.getWorkOrderId()});
            return AjaxResult.success();
        } else {
            return AjaxResult.error();
        }
    }

    @Override
    public AjaxResult receivedWorkOrder(WorkOrderRecord workOrderRecord, Long busUserId, String personTenantId) {
        if (StrUtil.isBlank(workOrderRecord.getWorkOrderId()) || busUserId == null || StrUtil.isBlank(personTenantId)) {
            return AjaxResult.error("数据异常");
        }
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderRecord.getWorkOrderId());

        if (ObjectUtil.isEmpty(workOrder)) {
            return AjaxResult.error("工单不存在");
        }
        //待接单以外的工单不能接单
        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, workOrder.getWorkOrderState())) {
            return AjaxResult.error("工单状态不正确，无法接单");
        }

        //接单
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.receivedWorkOrder(workOrderRecord, busUserId, personTenantId);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    @Transactional
    public AjaxResult editUrgencyDegree(WorkOrder workOrder, String phone) {
        if (StrUtil.isBlank(workOrder.getWorkOrderId()) || StrUtil.isBlank(workOrder.getUrgencyDegree())) {
            return AjaxResult.error("数据异常");
        }
        Date nowDate = DateUtils.getNowDate();

        WorkOrder wo = this.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        if (ObjectUtil.isEmpty(wo)) {
            return AjaxResult.error("工单不存在");
        }
        if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_DISPATCH, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED, wo.getWorkOrderState()))) {
            return AjaxResult.error("工单状态不正确，无法修改紧急程度");
        }


        String urgencyDegree = "";
        if (StrUtil.equals(WorkOrderConstants.URGENCY_DEGREE_NORMAL, workOrder.getUrgencyDegree())) {
            urgencyDegree = "普通";
        } else if (StrUtil.equals(WorkOrderConstants.URGENCY_DEGREE_EXIGENCY, workOrder.getUrgencyDegree())) {
            urgencyDegree = "紧急";
        } else if (StrUtil.equals(WorkOrderConstants.URGENCY_DEGREE_VERY_EXIGENCE, workOrder.getUrgencyDegree())) {
            urgencyDegree = "非常紧急";
        }
        //插入跟进记录
        WorkOrderRecord workOrderRecord = new WorkOrderRecord(workOrder.getWorkOrderId(), null,
                WorkOrderConstants.DISPLAY_TYPE_ORDER_MODIFIED, workOrder.getUpdateBy() + "(" + phone + ")" + "更新了紧急程度：" + urgencyDegree
                , null, null, nowDate);
        workOrderRecordService.insertWorkOrderRecord(workOrderRecord);

        workOrder.setUpdateTime(nowDate);
        int result = this.updateWorkOrder(workOrder);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult editEstimateTime(WorkOrder workOrder, String phone) {
        if (StrUtil.isBlank(workOrder.getWorkOrderId()) || workOrder.getEstimateTime() == null) {
            return AjaxResult.error("数据异常");
        }
        Date nowDate = DateUtils.getNowDate();

        WorkOrder wo = workOrderMapper.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        if (ObjectUtil.isEmpty(wo)) {
            return AjaxResult.error("工单不存在");
        }
        if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_DISPATCH, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_RECEIVING, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED, wo.getWorkOrderState()))) {
            return AjaxResult.error("工单状态不正确，无法修改预计上门时间");
        }

        //插入跟进记录
        WorkOrderRecord workOrderRecord = new WorkOrderRecord(workOrder.getWorkOrderId(), null,
                WorkOrderConstants.DISPLAY_TYPE_EXPECTED_VISIT_TIME, workOrder.getUpdateBy() + "(" + phone + ")" +
                "更新了预计上门时间：" + DateUtil.formatDateTime(workOrder.getEstimateTime()), null, null, nowDate);
        workOrderRecordService.insertWorkOrderRecord(workOrderRecord);

        workOrder.setUpdateTime(nowDate);
        int result = this.updateWorkOrder(workOrder);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }


    @Override
    public AjaxResult requestRejectionWorkOrder(WorkOrderRecord workOrderRecord, Long userId, String tenantId) {
        if (StrUtil.isBlank(workOrderRecord.getWorkOrderId()) || StrUtil.isBlank(workOrderRecord.getRecordContent())
                || userId == null || StrUtil.isBlank(tenantId)) {
            return AjaxResult.error("数据异常");
        }
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderRecord.getWorkOrderId());
        if (ObjectUtil.isEmpty(workOrder)) {
            return AjaxResult.error("工单不存在");
        }

        //申请拒接
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.requestRejectionWorkOrder(workOrderRecord, userId, tenantId);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public void weChatCallbackWorkOrderUnifiedPay(ParseParam parseParam) {
        WorkOrder workOrder = selectWorkOrderByWorkOrderId(parseParam.getOutTradeNo());
        if (ObjectUtil.isEmpty(workOrder)) {
            log.error("查询不到工单,参数：{}", JSONObject.toJSONString(parseParam));
            return;
        }
        // 保存微信支付回到参数
        WechatPayRecord wechatPayRecord = new WechatPayRecord();
        BeanUtil.copyProperties(parseParam, wechatPayRecord);
        wechatPayRecordService.insertWechatPayRecord(wechatPayRecord);

        Date nowDate = DateUtils.getNowDate();
        WorkOrderRecord record = new WorkOrderRecord(workOrder.getWorkOrderId(), WorkOrderConstants.RECORD_TYPE_USER_VISIBLE, WorkOrderConstants.DISPLAY_TYPE_ORDER_COMPLETED,
                "工单已在小程序缴费", null, null, nowDate);
        workOrder.setPaymentType(WorkOrderConstants.PAYMENT_TYPE_MINI_PROGRAM);
        workOrder.setPaymentTime(nowDate);

        // 更新工单状态
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        workOrderTypeServerRole.paymentCompletion(record);
    }

    @Override
    public AjaxResult auditDenialWorkOrder(WorkOrderRecord workOrderRecord, String username) {
        if (StrUtil.isBlank(workOrderRecord.getWorkOrderId()) || StrUtil.isBlank(username)) {
            return AjaxResult.error("数据异常");
        }
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderRecord.getWorkOrderId());
        if (ObjectUtil.isEmpty(workOrder)) {
            return AjaxResult.error("工单不存在");
        }
        //待派单,待接单以外的工单不能派单
        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_AUDIT, workOrder.getWorkOrderState())) {
            return AjaxResult.error("工单状态不正确，无法拒接");
        }
        //同意拒接
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.auditDenialWorkOrder(workOrderRecord, username);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult beingRepaired(WorkOrder workOrder) {
        //校验工单、维修前、维修后图片、费用项
        if (StrUtil.isBlank(workOrder.getWorkOrderId()) || workOrder.getWorkOrderChargeItemList().isEmpty()) {
            return AjaxResult.error("数据异常");
        }

        if (CollectionUtil.isEmpty(workOrder.getWorkOrderBeforePictureList()) ||
                workOrder.getWorkOrderBeforePictureList().size() > 6) {
            return AjaxResult.error("维修前图片数据异常");
        }

        if (CollectionUtil.isNotEmpty(workOrder.getWorkOrderAfterPictureList()) &&
                workOrder.getWorkOrderAfterPictureList().size() > 6) {
            return AjaxResult.error("维修后图片数量超过6张");
        }

        //校验维修收费项目金额
        boolean result = workOrder.getWorkOrderChargeItemList().stream().anyMatch(entry -> entry.getMaterialCost() == null ||
                entry.getMaterialCost().compareTo(BigDecimal.ZERO) < 0 || entry.getLaborCost() == null ||
                entry.getLaborCost().compareTo(BigDecimal.ZERO) < 0 || entry.getChargeQuantity() == null ||
                entry.getChargeQuantity().compareTo(BigDecimal.ZERO) < 0);
        if (result) {
            return AjaxResult.error("费用项数据异常");
        }

        //校验维修收费项目金额小数点位数
        boolean result1 = workOrder.getWorkOrderChargeItemList().stream().anyMatch(entry -> entry.getMaterialCost().scale() > 2 ||
                entry.getLaborCost().scale() > 2 || entry.getChargeQuantity().scale() > 0);
        if (result1) {
            return AjaxResult.error("费用项小数点位数异常");
        }

        WorkOrder wo = workOrderMapper.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        if (ObjectUtil.isEmpty(wo)) {
            return AjaxResult.error("工单不存在");
        }

        if (!(StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED, wo.getWorkOrderState()) ||
                StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_IN_DISPOSE, wo.getWorkOrderState()))) {
            return AjaxResult.error("工单状态不正确，无法编辑");
        }
        //编辑已接单、处理中工单
        wo.setWorkOrderBeforePictureList(workOrder.getWorkOrderBeforePictureList());
        wo.setWorkOrderAfterPictureList(workOrder.getWorkOrderAfterPictureList());
        wo.setWorkOrderChargeItemList(workOrder.getWorkOrderChargeItemList());
        wo.setWorkOrderExplain(workOrder.getWorkOrderExplain());
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(wo);
        int workOrderResult = workOrderTypeServerRole.beingRepaired();
        return workOrderResult > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult submitPaymentSlip(String workOrderId) {
        if (StrUtil.isBlank(workOrderId)) {
            return AjaxResult.error("数据异常");
        }
        WorkOrder workOrder = workOrderMapper.selectWorkOrderByWorkOrderId(workOrderId);
        if (ObjectUtil.isEmpty(workOrder)) {
            return AjaxResult.error("工单不存在");
        }
        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_IN_DISPOSE, workOrder.getWorkOrderState())) {
            return AjaxResult.error("工单状态不正确，无法提交缴费单");
        }
        if (StrUtil.isBlank(workOrder.getWorkOrderBeforePicture()) || StrUtil.isBlank(workOrder.getWorkOrderAfterPicture())) {
            return AjaxResult.error("请上传维修图片");
        }
        //编辑已接单、处理中工单
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int workOrderResult = workOrderTypeServerRole.submitPaymentSlip();
        return workOrderResult > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult revocationRejectionWorkOrder(WorkOrderRecord workOrderRecord, Long busUserId, String workOrderTenantId) {
        if (StrUtil.isBlank(workOrderRecord.getWorkOrderId()) || busUserId == null || StrUtil.isBlank(workOrderTenantId)) {
            return AjaxResult.error("数据异常");
        }
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderRecord.getWorkOrderId());
        if (ObjectUtil.isEmpty(workOrder)) {
            return AjaxResult.error("工单不存在");
        }
        //待派单,待接单以外的工单不能派单
        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_WAIT_AUDIT, workOrder.getWorkOrderState())) {
            return AjaxResult.error("工单状态不正确，无法撤销拒接申请");
        }

        //申请拒接
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.revocationRejectionWorkOrder(workOrderRecord, busUserId, workOrderTenantId);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public AjaxResult addPaymentDocument(WorkOrder workOrder, WorkOrderRecord workOrderRecord) {

        workOrder.setPaymentType(WorkOrderConstants.PAYMENT_TYPE_PAYMENT_VOUCHER);
        workOrder.setPaymentTime(DateUtils.getNowDate());

        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        int result = workOrderTypeServerRole.paymentCompletion(workOrderRecord);
        return result > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public List<WorkOrder> checkWorkOrder(List<WorkOrderPerson> workOrderPersonList) {
        WorkOrder workOrder = new WorkOrder();
        List<Long> busUserIds = new ArrayList<>();
        List<String> personTenantIds = new ArrayList<>();
        for (WorkOrderPerson workOrderPerson : workOrderPersonList) {
            busUserIds.add(workOrderPerson.getBusUserId());
            personTenantIds.add(workOrderPerson.getTenantId());
        }
        workOrder.setBusUserIds(busUserIds);
        workOrder.setPersonTenantIds(personTenantIds);
        List<WorkOrder> workOrderList = workOrderMapper.checkWorkOrder(workOrder);
        return workOrderList;
    }

    @Override
    public WorkOrder flatSelectWorkOrderByWorkOrderId(String workOrderId) {
        WorkOrder workOrder = workOrderMapper.selectWorkOrderByWorkOrderId(workOrderId);

        if (ObjectUtil.isNotNull(workOrder)) {
            WorkOrderEvaluate workOrderEvaluate = workOrderEvaluateService.selectWorkOrderEvaluateByWorkOrderId(workOrderId);
            workOrder.setWorkOrderEvaluation(workOrderEvaluate);

            String userDisplayType = "";
            if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_CANCELED, workOrder.getWorkOrderState())) {
                userDisplayType = WorkOrderConstants.DISPLAY_TYPE_ORDER_CANCELLED;
            } else if (StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED, workOrder.getWorkOrderState())) {
                userDisplayType = WorkOrderConstants.DISPLAY_TYPE_ORDER_ACCEPTED;
            }
            if (StrUtil.isNotBlank(userDisplayType)) {
                WorkOrderRecord record = workOrderRecordService.selectWorkOrderRecordByRecordTypeAndUserDisplayType(workOrderId,
                        WorkOrderConstants.RECORD_TYPE_USER_VISIBLE, userDisplayType);
                workOrder.setWorkOrderRecord(record);
            }

            //查询工单收费项
            if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_TYPE_INTERMEDIARY, workOrder.getWorkOrderType())) {
                List<WorkOrderChargeItem> workOrderChargeItems = workOrderChargeItemService.selectWorkOrderChargeItemByWorkOrderId(workOrderId);
                workOrder.setWorkOrderChargeItemList(workOrderChargeItems);
            }

        }
        return workOrder;
    }

    @Override
    public void workOrderOvertimeTask() {
        //查询工单
        List<WorkOrder> workOrderList = workOrderMapper.workOrderOvertimeTask();
        if (CollectionUtil.isNotEmpty(workOrderList)) {
            List<String> workOrderIdList = new ArrayList<>();
            LocalDateTime now = LocalDateTime.now();
            for (WorkOrder workOrder : workOrderList) {
                if (workOrder.getReceiveOrderTime() == null) {
                    log.error("工单{}的接单时间为空", workOrder.getWorkOrderId());
                    continue;
                }
                LocalDateTime receiveOrderTime = workOrder.getReceiveOrderTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_ONE_HOUR, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusHours(1);
                } else if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_TWO_HOUR, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusHours(2);
                } else if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_FOUR_HOUR, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusHours(4);
                } else if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_ONE_DAY, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusDays(1);
                } else if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_TWO_DAY, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusDays(2);
                } else if (StrUtil.equals(WorkOrderConstants.DISPOSE_TIME_LIMIT_THREE_DAY, workOrder.getDisposeTimeLimit())) {
                    receiveOrderTime = receiveOrderTime.plusDays(3);
                } else {
                    log.error("工单{}的处理时限异常", workOrder.getWorkOrderId());
                    continue;
                }
                if (receiveOrderTime.isBefore(now)) {
                    workOrderIdList.add(workOrder.getWorkOrderId());
                }
            }
            if (!workOrderIdList.isEmpty()) {
                workOrderMapper.updateOvertimeTask(workOrderIdList);
            }
        }
    }

    @Override
    public int softDeleteWorkOrderByWorkOrderId(String workOrderId) {
        WorkOrder workOrder = this.selectWorkOrderByWorkOrderId(workOrderId);
        if (ObjectUtil.isEmpty(workOrder)) {
            throw new ServiceException("工单不存在");
        }
        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_CANCELED, workOrder.getWorkOrderState())) {
            throw new ServiceException("工单状态不正确，无法删除");
        }
        return workOrderMapper.softDeleteWorkOrderByWorkOrderId(workOrderId);
    }

    @Override
    public AjaxResult countState(WorkOrder workOrder) {
        List<Map<String, Object>> mapList = workOrderMapper.countWorkOrderState(workOrder);
        for (int result = 1; result <= 8; result++) {
            String finalResult = String.valueOf(result);
            boolean b = mapList.stream().anyMatch(map -> StrUtil.equals(map.get("workOrderState").toString(), finalResult));
            if (!b) {
                //封装默认值0
                Map<String, Object> hashMap = new HashMap<>();
                hashMap.put("workOrderState", finalResult);
                hashMap.put("num", 0);
                mapList.add(hashMap);
            }
        }
        int num = workOrderMapper.countTimeoutFlag(workOrder);
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("workOrderState", "timeoutFlag");
        hashMap.put("num", num);
        mapList.add(hashMap);
        return AjaxResult.success(mapList);
    }

    @Override
    public List<WorkOrder> selectPendingWorkOrderList(Long workOrderPersonId) {
        WorkOrderPerson workOrderPerson = workOrderPersonService.selectWorkOrderPersonByWorkOrderPersonId(workOrderPersonId);
        if (ObjectUtil.isEmpty(workOrderPerson)) {
            throw new ServiceException("工单人员不存在");
        }
        WorkOrder workOrder = new WorkOrder();
        workOrder.setBusUserId(workOrderPerson.getBusUserId());
        workOrder.setPersonTenantId(workOrderPerson.getTenantId());
        return workOrderMapper.selectPendingWorkOrderList(workOrder);
    }

    @Override
    public List<WorkOrder> exportSelectWorkOrderList(WorkOrder workOrder) {
        List<WorkOrder> workOrderList;
        if (CollectionUtil.isNotEmpty(workOrder.getWorkOrderIds())) {
            workOrderList = workOrderMapper.selectWorkOrderByWorkOrderIds(workOrder.getWorkOrderIds());
            if (CollectionUtil.isNotEmpty(workOrderList)) {
                List<String> workOrders = workOrderList.stream().map(WorkOrder::getWorkOrderId).collect(Collectors.toList());
                List<WorkOrderChargeItem> workOrderChargeItemList = workOrderChargeItemService.selectWorkOrderChargeItemByWorkOrderIds(workOrders);
                if (CollectionUtil.isNotEmpty(workOrderChargeItemList)) {
                    Map<String, List<WorkOrderChargeItem>> collect = workOrderChargeItemList.stream().collect(Collectors.groupingBy(WorkOrderChargeItem::getWorkOrderId));
                    for (WorkOrder order : workOrderList) {
                        List<WorkOrderChargeItem> workOrderChargeItems = collect.get(order.getWorkOrderId());
                        if (CollectionUtil.isNotEmpty(workOrderChargeItems)) {
                            String itemName = workOrderChargeItems.stream().map(WorkOrderChargeItem::getItemName)
                                    .filter(StrUtil::isNotBlank).collect(Collectors.joining("|"));
                            order.setItemName(itemName);
                        }
                    }
                }
            }
        } else {
            workOrderList = this.selectWorkOrderList(workOrder);
        }
        return workOrderList;
    }

    @Override
    public AjaxResult applyTemporaryPassword(String workOrderId,String name,String phone,Long busUserId) {
        WorkOrder workOrder = selectWorkOrderByWorkOrderId(workOrderId);
        if (ObjectUtil.isEmpty(workOrder) || !workOrder.getWorkOrderState().equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED)){
            return AjaxResult.error("工单状态有误，无法申请临时密码");
        }

        WorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(workOrder);
        workOrderTypeServerRole.applyTemporaryPassword(name,phone,busUserId);
        return AjaxResult.success();
    }

    @Override
    public AjaxResult confirmLookHouseWorkOrder(WorkOrder workOrder, Long userId, String tenantId) {
        if (StrUtil.isBlank(workOrder.getWorkOrderId()) || userId == null || StrUtil.isBlank(tenantId)) {
            return AjaxResult.error("数据异常");
        }

        if (CollectionUtil.isEmpty(workOrder.getAttendantPictureList()) ||
                workOrder.getAttendantPictureList().size() > 6) {
            return AjaxResult.error("维修前图片数据异常");
        }
        WorkOrder wo = workOrderMapper.selectWorkOrderByWorkOrderId(workOrder.getWorkOrderId());
        if (ObjectUtil.isEmpty(wo)) {
            return AjaxResult.error("工单不存在");
        }

        if (!StrUtil.equals(WorkOrderConstants.WORK_ORDER_STATE_RECEIVED, wo.getWorkOrderState())) {
            return AjaxResult.error("工单状态不正确，无法编辑");
        }
        //编辑已接单、处理中工单
        wo.setAttendantPictureList(workOrder.getAttendantPictureList());
        wo.setWorkOrderExplain(workOrder.getWorkOrderExplain());
        IWorkOrderTypeServerRole workOrderTypeServerRole = new WorkOrderTypeServerRole(wo);
        int workOrderResult = workOrderTypeServerRole.confirmLookHouse(userId, tenantId);
        return workOrderResult > 0 ? AjaxResult.success() : AjaxResult.error();
    }

    @Override
    public List<WorkOrder> flatSelectWorkOrderList(WorkOrder workOrder) {
        return workOrderMapper.flatSelectWorkOrderList(workOrder);
    }
}
